package model

import (
	"context"
	"github.com/elastic/go-elasticsearch/v8/esapi"
	"github.com/elastic/go-elasticsearch/v8/esutil"
	"gorm.io/gorm"
	"mxshop_srvs/goods_srv/global"
	"strconv"
)

// Category 商品类型表
// 类型， 这个字段是否能为null， 这个字段应该设置为可以为null还是设置为空， 0
// 实际开发过程中 尽量设置为不为null
// https://zhuanlan.zhihu.com/p/73997266
// 这些类型我们使用int32还是int
type Category struct {
	BaseModel
	Name             string `gorm:"type:varchar(20);not null" json:"name"`
	ParentCategoryID *int32 `json:"parent"`
	// Category:连接表名 多对一的关系 一个
	ParentCategory *Category `json:"-"`
	// Category:连接表名 一对多的关系   foreignKey:指定当前模型的列作为连接表的外键    references:指定引用表的列名，其将被映射为连接表外键
	SubCategory []*Category `gorm:"foreignKey:ParentCategoryID;references:ID" json:"sub_category"` // 根据 id 去查询多个 ParentCategoryID
	Level       int32       `gorm:"type:int;not null;default:1" json:"level"`
	IsTab       bool        `gorm:"default:false;not null" json:"is_tab"`
}

// Brands 商品品牌表
type Brands struct {
	BaseModel
	Name string `gorm:"type:varchar(20);not null"`
	Logo string `gorm:"type:varchar(200);default:'';not null"`
}

// GoodsCategoryBrand 商品类型品牌表 多对多
type GoodsCategoryBrand struct {
	BaseModel
	CategoryID int32 `gorm:"type:int;index:idx_category_brand,unique"`
	Category   Category

	BrandsID int32 `gorm:"type:int;index:idx_category_brand,unique"`
	Brands   Brands
}

func (GoodsCategoryBrand) TableName() string {
	return "goodscategorybrand"
}

// Banner 轮播图
type Banner struct {
	BaseModel
	Image string `gorm:"type:varchar(200);not null"`
	Url   string `gorm:"type:varchar(200);not null"`
	Index int32  `gorm:"type:int;default:1;not null"`
}

type Goods struct {
	BaseModel

	CategoryID int32 `gorm:"type:int;not null"`
	Category   Category
	BrandsID   int32 `gorm:"type:int;not null"`
	Brands     Brands

	OnSale   bool `gorm:"default:false;not null"`
	ShipFree bool `gorm:"default:false;not null"`
	IsNew    bool `gorm:"default:false;not null"`
	IsHot    bool `gorm:"default:false;not null"`

	Name            string   `gorm:"type:varchar(50);not null"`
	GoodsSn         string   `gorm:"type:varchar(50);not null"`
	ClickNum        int32    `gorm:"type:int;default:0;not null"`
	SoldNum         int32    `gorm:"type:int;default:0;not null"`
	FavNum          int32    `gorm:"type:int;default:0;not null"`
	MarketPrice     float32  `gorm:"not null"`
	ShopPrice       float32  `gorm:"not null"`
	GoodsBrief      string   `gorm:"type:varchar(100);not null"`
	Images          GormList `gorm:"type:varchar(1000);not null"`
	DescImages      GormList `gorm:"type:varchar(1000);not null"`
	GoodsFrontImage string   `gorm:"type:varchar(200);not null"`
}

func (g *Goods) AfterCreate(tx *gorm.DB) (err error) {
	esModel := EsGoods{
		ID:          g.ID,
		CategoryID:  g.CategoryID,
		BrandsID:    g.BrandsID,
		OnSale:      g.OnSale,
		ShipFree:    g.ShipFree,
		IsNew:       g.IsNew,
		IsHot:       g.IsHot,
		Name:        g.Name,
		ClickNum:    g.ClickNum,
		SoldNum:     g.SoldNum,
		FavNum:      g.FavNum,
		MarketPrice: g.MarketPrice,
		GoodsBrief:  g.GoodsBrief,
		ShopPrice:   g.ShopPrice,
	}
	//_, err = global.EsClient.Index().Index(esModel.GetIndexName()).BodyJson(esModel).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	res, err := esapi.IndexRequest{
		DocumentID: strconv.Itoa(int(g.ID)),
		Index:      esModel.GetIndexName(),
		Body:       esutil.NewJSONReader(esModel),
	}.Do(context.Background(), global.EsClient)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	return nil
}

func (g *Goods) AfterUpdate(tx *gorm.DB) (err error) {
	esModel := EsGoods{
		ID:          g.ID,
		CategoryID:  g.CategoryID,
		BrandsID:    g.BrandsID,
		OnSale:      g.OnSale,
		ShipFree:    g.ShipFree,
		IsNew:       g.IsNew,
		IsHot:       g.IsHot,
		Name:        g.Name,
		ClickNum:    g.ClickNum,
		SoldNum:     g.SoldNum,
		FavNum:      g.FavNum,
		MarketPrice: g.MarketPrice,
		GoodsBrief:  g.GoodsBrief,
		ShopPrice:   g.ShopPrice,
	}

	//_, err = global.EsClient.Update().Index(esModel.GetIndexName()).Doc(esModel).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	res, err := esapi.UpdateRequest{
		DocumentID: strconv.Itoa(int(g.ID)),
		Index:      esModel.GetIndexName(),
		Body:       esutil.NewJSONReader(esModel),
	}.Do(context.Background(), global.EsClient)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	return nil
}

func (g *Goods) AfterDelete(tx *gorm.DB) (err error) {
	//_, err = global.EsClient.Delete().Index(EsGoods{}.GetIndexName()).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	res, err := esapi.DeleteRequest{
		Index:      EsGoods{}.GetIndexName(),
		DocumentID: strconv.Itoa(int(g.ID)),
	}.Do(context.Background(), global.EsClient)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	return nil
}
